package com.cjy.date;


import com.cjy.string.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;

/**
 * @author Cheng JiYe
 * @date 2020/3/19 22:12
 */
public class DateUtils {


    /**
     * @param date    时间
     * @param pattern 日期格式
     * @return
     */
    public static String getDateToString(Date date, String pattern) {
        if (StringUtils.isBlank(date) || StringUtils.isBlank(pattern)) {
            return "";
        }
        //设置字符串格式
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        return simpleDateFormat.format(date);
    }

    /**
     * 转换指定时间格式
     *
     * @param date
     * @param pattern
     * @return
     */
    public static String getDateToStringStart(Date date, String pattern) {
        return DateUtils.getDateToString(date, pattern);
    }


    /**
     * 获取本周第1天
     * <p>
     * 每星期第一天为：星期1，最后一天为星期日
     *
     * @return yyyy-mm-dd
     */
    public static String getMondayOfThisWeek() {
        return LocalDate.now().plusWeeks(0).with(DayOfWeek.MONDAY).toString();

    }


    /**
     * 获取本周最后1天
     * 每星期第一天为：星期一，最后一天为星期日
     *
     * @return yyyy-mm-dd
     */
    public static String getWeeklastday() {
        return LocalDate.now().plusWeeks(0).with(DayOfWeek.SUNDAY).toString();
    }

    /**
     * 获取上周第一天的时间 yyyy-mm-dd
     * 每星期第一天为：星期一，最后一天为星期日
     *
     * @return yyyy-mm-dd
     */
    public static String getLastWeekFirstDay() {
        return LocalDate.now().plusWeeks(-1).with(DayOfWeek.MONDAY).toString();

    }

    /**
     * 获取上周最后一天的时间 yyyy-mm-dd
     * 每星期第一天为：星期一，最后一天为星期日
     *
     * @return yyyy-mm-dd
     */
    public static String getLastWeekEndDay() {
        return LocalDate.now().plusWeeks(-1).with(DayOfWeek.SUNDAY).toString();
    }


    /**
     * 获取去年的本周的开始时间
     *
     * @return yyyy-mm-dd
     */
    public static String getLastYearThisWeekFirst() {
        return LocalDate.now().minusYears(1).with(DayOfWeek.MONDAY).toString();
    }


    /**
     * 获取去年的本周的结束时间
     *
     * @return yyyy-mm-dd
     */
    public static String getLastYearThisWeekEnd() {
        return LocalDate.now().minusYears(1).with(DayOfWeek.SUNDAY).toString();

    }


    /**
     * 获取本月第一天
     *
     * @return yyyy-mm-dd
     */
    public static String getThisMonthFirstDay() {
        return LocalDate.now().plusMonths(0).with(TemporalAdjusters.firstDayOfMonth()).toString();
    }


    /**
     * 获取本月最后一天
     *
     * @return yyyy-mm-dd
     */
    public static String getThisMonthEndDay() {
        return LocalDate.now().minusMonths(0).with(TemporalAdjusters.lastDayOfMonth()).toString();

    }


    /**
     * 获取上月第一天
     *
     * @return yyyy-mm-dd
     */
    public static String getLastMonthFirstDay() {
        return LocalDate.now().plusMonths(-1).with(TemporalAdjusters.firstDayOfMonth()).toString();
    }

    /**
     * 获取本月天数
     *
     * @return yyyy-mm-dd
     */
    public static int getThisMonthDayCount() {
        return LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
    }

    /**
     * 获取上月天数
     *
     * @return yyyy-mm-dd
     */
    public static int getLastMonthDayCount() {
        return LocalDate.now().plusMonths(-1).with(TemporalAdjusters.lastDayOfMonth()).getDayOfMonth();
    }

    /**
     * 获取上月最后一天
     * DateUtils
     *
     * @return yyyy-mm-dd
     */
    public static String getLastMonthEndDay() {
        return LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth()).toString();
    }


    /**
     * 获取去年本月的开始时间
     *
     * @return yyyy-mm-dd
     */
    public static String getLastYearMonthStartDay() {
        return LocalDate.now().plusYears(-1).with(TemporalAdjusters.firstDayOfMonth()).toString();
    }


    /**
     * 获取去年本月的结束时间
     *
     * @return yyyy-mm-dd
     */
    public static String getLastYearMonthEndDay() {
        return LocalDate.now().plusYears(-1).with(TemporalAdjusters.lastDayOfMonth()).toString();
    }


    /**
     * 获取本季第一天
     *
     * @return yyyy-mm-dd
     */
    public static String getThisQuarterFirstDay() {
        LocalDate inputDate = LocalDate.parse(getCurrentDate());
        Month month = inputDate.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        LocalDate localDate = LocalDate.of(inputDate.getYear(), firstMonthOfQuarter, 1);
        return localDate.toString();

    }


    /**
     * 获取本季度最后一天
     *
     * @return yyyy-mm-dd
     */
    public static String getThisQuarterEndDay() {
        LocalDate inputDate = LocalDate.parse(getCurrentDate());
        Month month = inputDate.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        Month endMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
        LocalDate localDate = LocalDate.of(inputDate.getYear(), endMonthOfQuarter, endMonthOfQuarter.length(inputDate.isLeapYear()));
        return localDate.toString();

    }


    /**
     * 获取上季度第一天
     *
     * @return yyyy-mm-dd
     */
    public static String getLastQuarterFirstDay() {
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.set(Calendar.MONTH, (startCalendar.get(Calendar.MONTH) / 3 - 1) * 3);
        startCalendar.set(Calendar.DAY_OF_MONTH, 1);
        return DateUtils.getDateToStringStart(startCalendar.getTime(), DateFormatConstant.C_YYYY_MM_DD);

    }


    /**
     * 获取上季度最后一天
     *
     * @return yyyy-mm-dd
     */
    public static String getLastQuarterEndDay() {
        Calendar endCalendar = Calendar.getInstance();
        endCalendar.set(Calendar.MONTH, (endCalendar.get(Calendar.MONTH) / 3 - 1) * 3 + 2);
        endCalendar.set(Calendar.DAY_OF_MONTH, endCalendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return DateUtils.getDateToStringStart(endCalendar.getTime(), DateFormatConstant.C_YYYY_MM_DD);

    }


    /**
     * 去年本季度开始日期
     *
     * @return yyyy-mm-dd
     */
    public static String getLastYearQuarterFirstDay() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.YEAR, -1);
        LocalDate inputDate = LocalDate.parse(getDateToString(c.getTime(), DateFormatConstant.C_YYYY_MM_DD));
        LocalDate localDate = LocalDate.of(inputDate.getYear(), inputDate.getMonth().firstMonthOfQuarter(), 1);
        return localDate.toString();
    }


    /**
     * 去年本季度结束日期
     *
     * @return yyyy-mm-dd
     */
    public static String getLastYearQuarterEndDay() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.YEAR, -1);
        LocalDate inputDate = LocalDate.parse(getDateToString(c.getTime(), DateFormatConstant.C_YYYY_MM_DD));
        Month month = inputDate.getMonth();
        Month firstMonthOfQuarter = month.firstMonthOfQuarter();
        Month endMonthOfQuarter = Month.of(firstMonthOfQuarter.getValue() + 2);
        LocalDate localDate = LocalDate.of(inputDate.getYear(), endMonthOfQuarter, endMonthOfQuarter.length(inputDate.isLeapYear()));
        return localDate.toString();
    }

    public static void main(String[] args) {
        System.out.println(getCurrentDayOfWeek());
    }

    /**
     * 获取当前时间，年份第一天
     *
     * @return yyyy-mm-dd
     */
    public static String getThisYearFirstDay() {
        return LocalDate.now().plusYears(0).with(TemporalAdjusters.firstDayOfYear()).toString();
    }

    /**
     * 获取当前时间，年份最后一天
     *
     * @return yyyy-mm-dd
     */
    public static String getThisYearEndDay() {
        return LocalDate.now().plusYears(0).with(TemporalAdjusters.lastDayOfYear()).toString();
    }


    /**
     * 获取去年的第一天
     *
     * @return
     */
    public static String getLastYearFirstDay() {
        return LocalDate.now().plusYears(-1).with(TemporalAdjusters.firstDayOfYear()).toString();
    }


    /**
     * 获取去年的最后一天
     * DateUtils
     *
     * @return
     */
    public static String getLastYearEndDay() {
        return LocalDate.now().plusYears(-1).with(TemporalAdjusters.lastDayOfYear()).toString();
    }


    /**
     * 获取当前日期，格式：yyyy-MM-dd
     *
     * @return
     */
    public static String getCurrentDate() {
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.format(new Date());
    }

    /**
     * 获取当前小时(24小时制)
     *
     * @return
     */
    public static int getCurrentHour() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * 获取当前(月份)日期
     *
     * @return
     */
    public static int getCurrentDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 获取当前(星期)日期(星期一为第一天)
     *
     * @return
     */
    public static int getCurrentDayOfWeek() {
        Calendar calendar = Calendar.getInstance();
        int day = calendar.get(Calendar.DAY_OF_WEEK);
        if (day == 1) {
            return 7;
        } else {
            return (day - 1);
        }
    }

    /**
     * 获取当前月份（年）
     *
     * @return
     */
    public static int getCurrentMonthOfYear() {
        Calendar calendar = Calendar.getInstance();
        return calendar.get(Calendar.MONTH) + 1;
    }

    /**
     * 获取本月所在季度的月份
     *
     * @return
     */
    public static int getCurrentMonthOfQuarter() {
        int month = getCurrentMonthOfYear();
        int qm = month % 3;
        if (qm == 0) {
            qm = 3;
        }
        return qm;
    }

    /**
     * 获取日期对象
     *
     * @param date yyyy-MM-dd
     * @return
     */
    public static Date getDate(String date) throws Exception {
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        return df.parse(date);
    }

    /**
     * 获取日期对象
     *
     * @param dateTime
     * @return
     * @throws Exception
     */
    public static Date getDateTime(String dateTime) throws Exception {
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.parse(dateTime);
    }

    /**
     * 获取当前日期，格式：yyyy-MM-dd
     *
     * @return
     */
    public static String getCurrentDate(String format) {
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat(format);
        return df.format(new Date());
    }

    /**
     * 获取当前时间，格式：yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    public static String getCurrentTime() {
        //设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(new Date());
    }


    /**
     * 得到n个月之后的月份
     *
     * @param cnt
     * @return
     */
    public static String getAfterMonth(int cnt) {

        // java.util包
        Calendar canlendar = Calendar.getInstance();

        // 日期减 如果不够减会将月变动
        canlendar.add(Calendar.MONTH, cnt);
        Date date = canlendar.getTime();

        SimpleDateFormat sdfd = new SimpleDateFormat("yyyyMM");
        String dateStr = sdfd.format(date);

        return dateStr;
    }

    /**
     * 得到n天之后的日期
     *
     * @param date
     * @param cnt
     * @return
     * @throws Exception
     */
    public static String getAfterMonthDate(String date, int cnt) throws Exception {
        SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");
        Date inDate = sdfd.parse(date);

        // java.util包
        Calendar canlendar = Calendar.getInstance();
        canlendar.setTime(inDate);
        canlendar.add(Calendar.MONTH, cnt);
        Date outDate = canlendar.getTime();
        String dateStr = sdfd.format(outDate);

        return dateStr;
    }

    /**
     * 得到n天之后的日期
     *
     * @param days
     * @return
     */
    public static String getAfterDayDate(String date, int days) throws Exception {
        SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd");
        Date inDate = sdfd.parse(date);

        Calendar canlendar = Calendar.getInstance(); // java.util包
        canlendar.setTime(inDate);
        canlendar.add(Calendar.DATE, days); // 日期减 如果不够减会将月变动
        Date outDate = canlendar.getTime();
        String dateStr = sdfd.format(outDate);

        return dateStr;
    }

    /**
     * 得到n天之后的时间
     *
     * @param days
     * @return
     */
    public static String getAfterDayTime(String time, int days) throws Exception {
        SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date inDate = sdfd.parse(time);

        Calendar canlendar = Calendar.getInstance(); // java.util包
        canlendar.setTime(inDate);
        canlendar.add(Calendar.DATE, days); // 日期减 如果不够减会将月变动
        Date outDate = canlendar.getTime();
        String dateStr = sdfd.format(outDate);

        return dateStr;
    }

    /**
     * 得到小时之后的时间
     *
     * @param hours
     * @return
     */
    public static String getAfterHourTime(String time, int hours) throws Exception {
        SimpleDateFormat sdfd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date inDate = sdfd.parse(time);

        Calendar canlendar = Calendar.getInstance(); // java.util包
        canlendar.setTime(inDate);
        canlendar.add(Calendar.HOUR_OF_DAY, hours); // 日期减 如果不够减会将月变动
        Date outDate = canlendar.getTime();
        String dateStr = sdfd.format(outDate);

        return dateStr;
    }

    /**
     * @param startTime
     * @param endTime
     * @return
     */
    public static int getDiffYear(String startTime, String endTime) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        try {
            //long aa=0;
            int years = (int) (((fmt.parse(endTime).getTime() - fmt.parse(startTime).getTime()) / (1000 * 60 * 60 * 24)) / 365);
            return years;
        } catch (Exception e) {
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            return 0;
        }
    }

    /**
     * 获取开始时间和结束时间之间相差的小时
     *
     * @param startTime 开始时间，格式：yyyy-MM-dd HH:mm:ss
     * @param endTime   结束时间，格式：yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static int getDiffDays(String startTime, String endTime) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            //long aa=0;
            int hours = (int) ((fmt.parse(endTime).getTime() - fmt.parse(startTime).getTime()) / (1000 * 60 * 60 * 24));
            return hours;
        } catch (Exception e) {
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            return 0;
        }
    }

    /**
     * 获取开始时间和结束时间之间相差的小时
     *
     * @param startTime 开始时间，格式：yyyy-MM-dd HH:mm:ss
     * @param endTime   结束时间，格式：yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static long getDiffHour(String startTime, String endTime) {
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            //long aa=0;
            long hours = (long) ((fmt.parse(endTime).getTime() - fmt.parse(startTime).getTime()) / (1000 * 60 * 60));
            return hours;
        } catch (Exception e) {
            // 如果throw java.text.ParseException或者NullPointerException，就说明格式不对
            return 0;
        }
    }

    /**
     * <li>功能描述：时间相减得到天数
     *
     * @param beginDateStr
     * @param endDateStr
     * @return long
     * @author Administrator
     */
    public static long getDaySub(String beginDateStr, String endDateStr) {
        long day = 0;
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        java.util.Date beginDate = null;
        java.util.Date endDate = null;

        try {
            beginDate = format.parse(beginDateStr);
            endDate = format.parse(endDateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        day = (endDate.getTime() - beginDate.getTime()) / (24 * 60 * 60 * 1000);
        //System.out.println("相隔的天数="+day);

        return day;
    }

    /**
     * 获取日期年份
     *
     * @return
     */
    public static int getYear(String date) {
        if (StringUtils.isEmpty(date) && date.length() >= 4) {
            return 0;
        }
        return Integer.parseInt(date.substring(0, 4));
    }

    /**
     * 获取日期月份
     *
     * @param date yyyy-MM-dd格式
     * @return
     */
    public static int getMonth(String date) {
        if (StringUtils.isEmpty(date) && date.length() >= 7) {
            return 0;
        }
        return Integer.parseInt(date.substring(5, 7));
    }

    /**
     * 获取日期所在年份的第几周
     *
     * @param date yyyy-MM-dd格式
     * @return
     */
    public static int getWeekOfYear(String date) throws Exception {
        if (StringUtils.isEmpty(date)) {
            return 0;
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date inDate = sdf.parse(date);

        Calendar canlendar = Calendar.getInstance(); // java.util包
        canlendar.setTime(inDate);

        return canlendar.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * @param year
     * @param week
     * @return
     * @throws Exception
     */
    public static String getYearWeekFirstDay(int year, int week) throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, 0, 1);
        int dayOfWeek = 7 - calendar.get(Calendar.DAY_OF_WEEK) + 1;//算出第一周还剩几天 +1是因为1号是1天
        week = week - 2;//周数减去第一周再减去要得到的周
        calendar.add(Calendar.DAY_OF_YEAR, week * 7 + dayOfWeek);
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    /**
     * 获取指定年
     *
     * @param year
     * @param week
     * @return
     * @throws Exception
     */
    public static String getYearWeekLastDay(int year, int week) throws Exception {
        Calendar calendar = Calendar.getInstance();
        calendar.set(year, 0, 1);
        int dayOfWeek = 7 - calendar.get(Calendar.DAY_OF_WEEK) + 1;//算出第一周还剩几天 +1是因为1号是1天
        week = week - 2;//周数减去第一周再减去要得到的周
        calendar.add(Calendar.DAY_OF_YEAR, week * 7 + dayOfWeek + 6);
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    /**
     * 获取日期月份
     *
     * @param month
     * @param cnt
     * @return
     */
    public static int getMonthAdd(int month, int cnt) {
        cnt = cnt % 12;
        int m = month + cnt;
        if (m <= 0) {
            m = m + 12;
        }
        return m;
    }


    /**
     * 将短时间格式字符串转换为时间 yyyy-MM-dd
     *
     * @param strDate
     * @return
     */
    public static Date strToDate(String strDate, String pattern) {
        SimpleDateFormat formatter = new SimpleDateFormat(pattern);
        ParsePosition pos = new ParsePosition(0);
        Date strtodate = formatter.parse(strDate, pos);
        return strtodate;
    }

    /**
     * 格式化日期
     *
     * @return
     */
    public static Date fomatDate(String date) {
        if (StringUtils.isEmpty(date)) {
            return null;
        }
        try {
            String formatStr = "yyyy-MM-dd";
            if (date.contains("年") && date.contains("月") && date.contains("日")) {
                formatStr = "yyyy年MM月dd日";
            } else if (date.contains("/")) {
                formatStr = "yyyy/MM/dd";
            }
            return fomatDate(date, formatStr);
        } catch (Exception e) {
            System.err.println("日期转换出错！" + date);
            return null;
        }
    }

    /**
     * 格式化日期
     *
     * @return
     */
    public static Date fomatTime(String time) {
        if (StringUtils.isEmpty(time)) {
            return null;
        }
        try {
            String formatStr = "yyyy-MM-dd HH:mm:ss";
            if (time.contains("年") && time.contains("月") && time.contains("日")) {
                formatStr = "yyyy年MM月dd日 HH:mm:ss";
            } else if (time.contains("/")) {
                formatStr = "yyyy/MM/dd HH:mm:ss";
            }
            return fomatDate(time, formatStr);
        } catch (Exception e) {
            System.err.println("日期时间转换出错！" + time);
            return null;
        }
    }

    /**
     * 格式化日期
     *
     * @return
     */
    public static Date fomatDate(String date, String format) {
        DateFormat fmt = new SimpleDateFormat(format);
        try {
            return fmt.parse(date);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * @param s
     * @param e
     * @return boolean
     * @throws
     * @Title: compareDate
     * @Description: TODO(日期比较 ， 如果s > = e 返回true 否则返回false)
     * @author fh
     */
    public static boolean compareTime(String s, String e) {
        if (fomatTime(s) == null || fomatTime(e) == null) {
            return false;
        }
        return fomatTime(s).getTime() >= fomatTime(e).getTime();
    }

    /**
     * @param s
     * @param e
     * @return boolean
     * @throws
     * @Title: compareDate
     * @Description: TODO(日期比较 ， 如果s > = e 返回true 否则返回false)
     * @author fh
     */
    public static boolean compareDate(String s, String e) {
        if (fomatDate(s) == null || fomatDate(e) == null) {
            return false;
        }
        return fomatDate(s).getTime() >= fomatDate(e).getTime();
    }

}
